package de.ba.se.roboter.controller;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.Timer;

import de.ba.se.roboter.data.Orienation;
import de.ba.se.roboter.data.Robot;
import de.ba.se.roboter.ui.ConfigView;
import de.ba.se.roboter.ui.MainView;

/**
 * Der Controller, der die Initialisierung der GUI übernimmt und die GUI mit dem Datenmodell verknüpft.
 * 
 * @author Sebastian Tönse
 *
 */
public class MainController {
	
	private MainView view;
	
	private ConfigView configView;
	
	private Robot robot;
	
	private Timer timer;
	
	/**
	 * default c-tor
	 */
	public MainController() {
		this.view = new MainView(this);
		this.configView = new ConfigView(view, this);
	}
	
	/**
	 * Setzt die Konfiguration für den {@link Robot}.
	 * 
	 * @param orienation Initiale Blickrichtung.
	 * @param width Feldbreite.
	 * @param height Feldhöhr.
	 */
	public void setConfiguration(Orienation orienation, int width, int height) {
		robot = new Robot(orienation, new boolean[width][height]);
		view.getRobotPanel().initUiField(robot);
	}

	/**
	 * Startet den {@link Timer}, über den der {@link Robot} seine Schrittgeschwindigkeit bekommt.
	 * @param i Verzögerung in 0,1 sec.
	 */
	public void start(int i) {
		if (timer == null) {
			timer = new Timer(i * 100, new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (!robot.turn()) {
						timer.stop();
						JOptionPane.showMessageDialog(view, "Robot hat den Rand des Feldes erreicht!");
					}
					DefaultListModel<String> model = (DefaultListModel<String>) view.getControlPanel().getStepList().getModel();
					model.addElement(String.format("%d: %s", robot.getStepCount(), robot.getMethods()));
					view.getRobotPanel().initUiField(robot);
					view.getRobotPanel().repaint();
				}
			});
		}
		timer.setDelay(i * 100);
		timer.start();
	}

	/**
	 * Macht einen einzelnen Schritt.
	 */
	public void step() {
		if (!robot.turn()) {
			JOptionPane.showMessageDialog(view, "Robot hat den Rand des Feldes erreicht!");
		}
		view.getRobotPanel().initUiField(robot);
		view.getRobotPanel().repaint();
	}

	/**
	 * Stoppt den {@link Timer}.
	 */
	public void stop() {
		timer.stop();
	}

	/**
	 * Stoppt den {@link Timer} für einen Neustart des {@link Robot}.
	 */
	public void showConfigView() {
		if (timer != null) timer.stop();
		this.configView.setVisible(true);
		this.view.getControlPanel().getStepList().setModel(new DefaultListModel<String>());
		this.view.getRobotPanel().repaint();
	}

	/**
	 * Speichert das entstandene Bild als Datei unter dem angegebenen Pfad.
	 * @param f Datei, die den Pfad enthält.
	 */
	public void saveImage(final File f) {
		final Dimension dimension = view.getRobotPanel().getPreferredSize();
		final BufferedImage image = new BufferedImage(dimension.width - 20, dimension.height - 20, BufferedImage.TYPE_INT_RGB);
		final Graphics graphics = image.getGraphics();
		graphics.setColor(Color.WHITE);
		graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
		graphics.setColor(Color.BLACK);
		final boolean[][] field = robot.getField();
		for (int i = 0; i < field.length; i++) {
			for (int j = 0; j < field[0].length; j++) {
				if(field[i][j]) {
					graphics.fillRect(i * 42, j * 42, 42, 42);
				} else {
					graphics.drawRect(i * 42, j * 42, 42, 42);
				}
			}
		}
		try {
			if (ImageIO.write(image, "PNG", f)) {
				JOptionPane.showMessageDialog(view, "Bild gespeichert!", "Meldung", JOptionPane.INFORMATION_MESSAGE);
			}
		} catch (IOException e) {
			JOptionPane.showConfirmDialog(view, e.getMessage());
			e.printStackTrace();
		}
	}
}
